package Test;

import static org.junit.Assert.*;

import org.junit.Test;

import LatentTicTacToe.Data.Move;
import LatentTicTacToe.Data.SimulationBoard;

public class SimulationBoardTest {

	@Test
	public void isTerminalTestWithPlayerOneWinning() {
		byte[][] situation = new byte[][]{{1, 1, 1},
										  {2, 2, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(1, board.isTerminal());
	}
	
	@Test
	public void isTerminalTestWithPlayerTwoWinningOne() {
		byte[][] situation = new byte[][]{{1, 1, 1},
										  {2, 2, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(1, board.isTerminal());
	}
	
	@Test
	public void isTerminalTestWithPlayerTwoWinning() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {0, 0, 1},
										  {2, 2, 2}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)1);
		
		assertEquals(2, board.isTerminal());
	}
	
	@Test
	public void isTerminalTestWithNonterminalSituation() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {2, 2, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)1);
		
		assertEquals(0, board.isTerminal());
	}
	
	@Test
	public void isTerminalTestWithFullSituation() {
		byte[][] situation = new byte[][]{{1, 1, 2},
										  {2, 2, 1},
										  {1, 2, 1}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(-1, board.isTerminal());
	}
	
	@Test
	public void isTerminalTestWithFullSituationAndPlayerOneWinning() {
		byte[][] situation = new byte[][]{{1, 2, 2},
										  {2, 2, 1},
										  {1, 1, 1}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(1, board.isTerminal());
	}
	
	@Test
	public void isTerminalForMoveTestWithFullSituation() {
		byte[][] situation = new byte[][]{{1, 1, 2},
										  {2, 2, 1},
										  {1, 2, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)1);
		
		assertEquals(-1, board.isTerminalForMove(new Move((byte)2, (byte)2)));
	}
	
	@Test
	public void isTerminalForMoveTestWithPlayerOneWinning() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {2, 2, 1},
										  {2, 1, 2}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)1);
		
		assertEquals(1, board.isTerminalForMove(new Move((byte)0, (byte)2)));
	}
	
	@Test
	public void isTerminalForMoveTestWithPlayerTwoWinning() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {2, 2, 0},
										  {2, 1, 1}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(2, board.isTerminalForMove(new Move((byte)1, (byte)2)));
	}
	
	@Test
	public void isTerminalForMoveTestWithNooneWinning() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {2, 0, 0},
										  {2, 1, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(0, board.isTerminalForMove(new Move((byte)2, (byte)1)));
	}
	
	@Test
	public void getAvailableMovesTest() {
		byte[][] situation = new byte[][]{{1, 1, 0},
										  {2, 2, 0},
										  {2, 1, 1}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		Move move1 = new Move((byte)0, (byte)2);
		Move move2 = new Move((byte)1, (byte)2);
		
		assertEquals(2, board.getAvailableMoves().size());
		assertEquals(true,  board.getAvailableMoves().contains(move1));
		assertEquals(true,  board.getAvailableMoves().contains(move2));		
	}
	
	@Test
	public void getAvailableMovesTestWithTerminalSituation() {
		byte[][] situation = new byte[][]{{1, 1, 2},
										  {2, 2, 0},
										  {2, 1, 1}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		assertEquals(0, board.getAvailableMoves().size());	
	}
	
	@Test
	public void makeMoveTest() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00", situation, (byte)1);
		board.makeMove(new Move((byte)1, (byte)2));
		
		assertEquals(2, board.getCurrentPlayer());
		assertEquals("0.00.12", board.getId());
		
		situation[1][2] = 2;
		
		for (int i = 0; i < situation.length; i++) {
			for (int j = 0; j < situation.length; j++) {
				assertEquals(situation[j][i], board.getSituation()[j][i]);
			}
		}
	}
	
	@Test
	public void makeMoveTestWithFirstMove() {
		byte[][] situation = new byte[][]{{0, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("", situation, (byte)1);
		board.makeMove(new Move((byte)1, (byte)2));
		
		assertEquals(2, board.getCurrentPlayer());
		assertEquals("0", board.getId());

		for (int i = 0; i < situation.length; i++) {
			for (int j = 0; j < situation.length; j++) {
				assertEquals(situation[j][i], board.getSituation()[j][i]);
			}
		}
	}
	
	@Test
	public void makeMoveAndReverseMoveTest() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00", situation, (byte)1);
		
		board.makeMove(new Move((byte)1, (byte)2));
		board.makeMove(new Move((byte)2, (byte)2));
		
		board.reverseMove();
		
		situation[1][2] = 2;
		
		assertEquals(2, board.getCurrentPlayer());
		assertEquals("0.00.12", board.getId());
		
		for (int i = 0; i < situation.length; i++) {
			for (int j = 0; j < situation.length; j++) {
				assertEquals(situation[j][i], board.getSituation()[j][i]);
			}
		}
	}
	
	@Test
	public void isAfterInvalidMoveTestWithoutInvalidMove() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00", situation, (byte)2);
		
		assertEquals(false, board.isAfterInvalidMove());
	}
	
	@Test
	public void isAfterInvalidMoveTestWithoutInvalidMoveOne() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0", situation, (byte)2);
		
		assertEquals(false, board.isAfterInvalidMove());
	}
	
	
	@Test
	public void isAfterInvalidMoveTestWithInvalidmove() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00.00", situation, (byte)2);
		
		assertEquals(true, board.isAfterInvalidMove());
	}
	
	@Test
	public void removeInvalidMoveTestWithoutInvalidMove() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00", situation, (byte)2);
		
		assertEquals(null, board.removeInvalidMove());
		assertEquals("0.00", board.getId());
	}
	
	@Test
	public void removeInvalidMoveTestWithInvalidMove() {
		byte[][] situation = new byte[][]{{1, 0, 0},
										  {0, 0, 0},
										  {0, 0, 0}};
		
		SimulationBoard board = new SimulationBoard("0.00.00", situation, (byte)2);
		
		assertEquals(new Move((byte)0, (byte)0), board.removeInvalidMove());
		assertEquals("0", board.getId());
	}

}
